package com.sf.fy.uav.service.impl;

import cn.hutool.core.util.DesensitizedUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sf.fy.uav.common.enums.CommodityStatusEnum;
import com.sf.fy.uav.common.enums.ScenicSpotStatusEnum;
import com.sf.fy.uav.common.request.operate.BusinessReq;
import com.sf.fy.uav.common.request.operate.MerchantReq;
import com.sf.fy.uav.common.response.operational.BusinessRes;
import com.sf.fy.uav.common.response.operational.MerchantRes;
import com.sf.fy.uav.common.utils.BeanUtil;
import com.sf.fy.uav.common.utils.PhoneEncoderUtil;
import com.sf.fy.uav.common.utils.RespJsonPageData;
import com.sf.fy.uav.common.utils.Rs;
import com.sf.fy.uav.controller.CommodityRest;
import com.sf.fy.uav.controller.OrderCommodityRest;
import com.sf.fy.uav.entity.Business;
import com.sf.fy.uav.entity.File;
import com.sf.fy.uav.entity.Commodity;
import com.sf.fy.uav.entity.OrderCommodity;
import com.sf.fy.uav.mapper.FileMapper;
import com.sf.fy.uav.mapper.BusinessMapper;
import com.sf.fy.uav.rest.ScenicSpotRest;
import com.sf.fy.uav.service.IBusinessService;
import com.sf.fy.uav.withdrawal.entity.ScenicSpot;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author LTQ
 * @since 2023-12-07
 */
@Service
@RequiredArgsConstructor
public class BusinessServiceImpl extends ServiceImpl<BusinessMapper, Business> implements IBusinessService {
    private final BusinessMapper businessMapper;

    private final CommodityRest commodityRest;

    private final ScenicSpotRest scenicSpotRest;

    private final PhoneEncoderUtil phoneEncoderUtil;

    private final OrderCommodityRest orderCommodityRest;

    private static final Integer CONST_NUM = 0;
    private static final Integer NAME_CHECK = 15;
    private static final Integer ADDRESS_CHECK = 80;
    private static final Integer PHONE_CHECK = 11;

    private static final String SCENIC_SPOT_ID = "";

    @Autowired
    private FileMapper fileMapper;

    @Override
    public List<Business> getBusinesses() {
        QueryWrapper<Business> businessQueryWrapper = new QueryWrapper<>();
        businessQueryWrapper.eq("status", ScenicSpotStatusEnum.NORMAL.getValue());
        return businessMapper.selectList(businessQueryWrapper);
    }


    @Override
    public List<Business> getBusinessesByScenicSpotId(String scenicSpotId) {
        QueryWrapper<Business> businessQueryWrapper = new QueryWrapper<>();
        businessQueryWrapper.eq("status", ScenicSpotStatusEnum.NORMAL.getValue());
        if (!ObjectUtils.isEmpty(scenicSpotId)) {
            businessQueryWrapper.eq("scenic_spot_id", scenicSpotId);
        }

        return businessMapper.selectList(businessQueryWrapper);
    }

    @Override
    public RespJsonPageData<BusinessRes> getPageBusiness(BusinessReq businessReq) {
        if (StringUtils.isBlank(businessReq.getScenicSpotId())) {
            throw new RuntimeException("景区id不能为空!");
        }
        LambdaQueryWrapper<Business> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.isNotBlank(businessReq.getName()), Business::getName, businessReq.getName())
                .eq(!ObjectUtils.isEmpty(businessReq.getStatus()), Business::getStatus, businessReq.getStatus())
                .eq(Business::getScenicSpotId, businessReq.getScenicSpotId())
                .orderByDesc(Business::getCreateTime);
        Page<Business> businessPageList = businessMapper.selectPage(new Page<>(businessReq.getPage(), businessReq.getSize()), wrapper);
        Set<String> businessIdSet = businessPageList.getRecords().stream().map(Business::getId).collect(Collectors.toSet());
        List<Commodity> commodityList = commodityRest.selectProductByBusinessIds(businessIdSet);
        List<BusinessRes> businessResList = BeanUtil.copyProperties(businessPageList.getRecords(), BusinessRes.class);
        if (!CollectionUtils.isEmpty(businessResList)){
            businessResList.forEach(businessRes -> {
                AtomicInteger sum = new AtomicInteger();
                AtomicInteger amountSum = new AtomicInteger();
                AtomicInteger alreadyListed = new AtomicInteger();
                commodityList.forEach(commodity -> {
                    if (StringUtils.isNotBlank(businessRes.getId()) && commodity.getBusinessId().equals(businessRes.getId())) {
                        amountSum.addAndGet(commodity.getAmount());
                        if(!CollectionUtils.isEmpty(businessReq.getOrderCommodityNewList())){
                            businessReq.getOrderCommodityNewList().forEach(orderCommodity->{
                                if(commodity.getId().equals(orderCommodity.getCommodityId())){
                                    sum.addAndGet(orderCommodity.getCnt());
                                }
                            });
                        }
                        if (CommodityStatusEnum.GROUNDING.getValue().equals(commodity.getStatus())) {
                            alreadyListed.addAndGet(commodity.getAmount());
                        }
                    }
                });
                businessRes.setStatusName(ScenicSpotStatusEnum.getDesc(businessRes.getStatus()));
                businessRes.setAmount(amountSum.get()+sum.get());
                businessRes.setAlreadyListed(alreadyListed.get());
            });
        }
        return RespJsonPageData.success(businessResList, businessPageList.getTotal());
    }

    @Override
    public RespJsonPageData<MerchantRes> getPageMerchant(MerchantReq merchantReq) {
        LambdaQueryWrapper<Business> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.isNotBlank(merchantReq.getName()), Business::getName, merchantReq.getName())
                .like(StringUtils.isNotBlank(merchantReq.getBrand()), Business::getBrand, merchantReq.getBrand())
                .eq(!ObjectUtils.isEmpty(merchantReq.getStatus()), Business::getStatus, merchantReq.getStatus())
                .orderByDesc(Business::getCreateTime);
        Page<Business> merchantPageList = businessMapper.selectPage(new Page<>(merchantReq.getPage(), merchantReq.getSize()), wrapper);
        Set<String> businessIdSet = merchantPageList.getRecords().stream().map(Business::getId).collect(Collectors.toSet());
        Set<String> scenicSpotIdSet = merchantPageList.getRecords().stream().map(Business::getScenicSpotId).collect(Collectors.toSet());
        List<ScenicSpot> scenicSpots = scenicSpotRest.selectScenicSpotListByIds(scenicSpotIdSet);
        Map<String, ScenicSpot> scenicSpotMap = scenicSpots.stream().collect(Collectors.toMap(ScenicSpot::getId, each -> each, (value1, value2) -> value1));
        List<Commodity> commodityList = commodityRest.selectProductByBusinessIds(businessIdSet);
        List<MerchantRes> merchantResList = BeanUtil.copyProperties(merchantPageList.getRecords(), MerchantRes.class);
        if (!CollectionUtils.isEmpty(merchantResList)) {
            List<String> merchantResFileIds = merchantResList.stream().map(MerchantRes::getFileId).collect(Collectors.toList());
            List<File> files = fileMapper.selectBatchIds(merchantResFileIds);
            merchantResList.forEach(merchantRes -> {
                files.forEach(file -> {
                    if (file.getId().equals(merchantRes.getFileId())) {
                        merchantRes.setLogo(file.getFilePath());
                    }
                });
                if (!ObjectUtils.isEmpty(scenicSpotMap.get(merchantRes.getScenicSpotId()))) {
                    merchantRes.setScenicSpotName(scenicSpotMap.get(merchantRes.getScenicSpotId()).getName());
                }
                AtomicInteger sum = new AtomicInteger();
                AtomicInteger amountSum = new AtomicInteger();
                AtomicInteger alreadyListed = new AtomicInteger();
                commodityList.forEach(commodity -> {
                    if (StringUtils.isNotBlank(merchantRes.getId()) && commodity.getBusinessId().equals(merchantRes.getId())) {
                        amountSum.addAndGet(commodity.getAmount());
                        if (!CollectionUtils.isEmpty(merchantReq.getOrderCommodityNewList())){
                            merchantReq.getOrderCommodityNewList().forEach(orderCommodity->{
                                if(commodity.getId().equals(orderCommodity.getCommodityId())){
                                    sum.addAndGet(orderCommodity.getCnt());
                                }
                            });
                        }
                        if (CommodityStatusEnum.GROUNDING.getValue().equals(commodity.getStatus())) {
                            alreadyListed.addAndGet(commodity.getAmount());
                        }
                    }
                });
                merchantRes.setStatusName(ScenicSpotStatusEnum.getDesc(merchantRes.getStatus()));
                merchantRes.setIntegrityAddress(merchantRes.getProvince() + merchantRes.getCity() + merchantRes.getDistrict() + merchantRes.getAddress());
                merchantRes.setPhone(DesensitizedUtil.desensitized(phoneEncoderUtil.decryptString(merchantRes.getPhone()), DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
                merchantRes.setAmount(amountSum.get()+sum.get());
                merchantRes.setAlreadyListed(alreadyListed.get());
            });
        }
        return RespJsonPageData.success(merchantResList, merchantPageList.getTotal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Rs<Integer> save(MerchantReq merchantReq) {
        batchCheckMerchantReq(merchantReq);
        Date date = new Date();
        Business business = BeanUtil.copyProperties(merchantReq, Business.class);
        business.setCreateTime(date);
        business.setUpdateTime(date);
        business.setPhone(phoneEncoderUtil.encryptString(merchantReq.getPhone()));
        int con = businessMapper.insert(business);
        if (con > CONST_NUM) {
            return Rs.success(CONST_NUM);
        } else {
            return Rs.failed();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Rs<Integer> updateById(MerchantReq merchantReq) {
        if (StringUtils.isBlank(merchantReq.getId())) {
            throw new RuntimeException("商家id不能为空");
        }
        batchCheckMerchantReq(merchantReq);
        Business business = BeanUtil.copyProperties(merchantReq, Business.class);
        business.setPhone(phoneEncoderUtil.encryptString(merchantReq.getPhone()));
        business.setUpdateTime(new Date());
        int updateCum = businessMapper.updateById(business);
        if (updateCum > CONST_NUM) {
            return Rs.success(CONST_NUM);
        } else {
            return Rs.failed();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Rs<Integer> deletedBusiness(MerchantReq merchantReq) {
        if (StringUtils.isBlank(merchantReq.getId())) {
            throw new RuntimeException("投放点id不能为空");
        }
        if (StringUtils.isBlank(merchantReq.getProcessedBy())) {
            throw new RuntimeException("操作人不能为空");
        }
        Business business = BeanUtil.copyProperties(merchantReq, Business.class);
        business.setScenicSpotId(SCENIC_SPOT_ID);
        business.setUpdateTime(new Date());
        int updateCum = businessMapper.updateById(business);
        if (updateCum > CONST_NUM) {
            return Rs.success(CONST_NUM);
        } else {
            return Rs.failed();
        }
    }

    @Override
    public List<Business> getBusinessesByBusinessIds(Set<String> businessIds) {
        return businessMapper.selectBatchIds(businessIds);
    }

    private void batchCheckMerchantReq(MerchantReq merchantReq) {
        if (StringUtils.isBlank(merchantReq.getBrand())) {
            throw new RuntimeException("商家品牌不能为空");
        }
        if (merchantReq.getBrand().length() > NAME_CHECK) {
            throw new RuntimeException("商家品牌长度不能超过15位");
        }
        if (StringUtils.isBlank(merchantReq.getName())) {
            throw new RuntimeException("商家名称不能为空");
        }
        if (merchantReq.getName().length() > NAME_CHECK) {
            throw new RuntimeException("商家名称长度不能超过15位");
        }
        if (StringUtils.isBlank(merchantReq.getProvinceCode())) {
            throw new RuntimeException("省编号不能为空");
        }
        if (StringUtils.isBlank(merchantReq.getProvince())) {
            throw new RuntimeException("省名不能为空");
        }
        if (StringUtils.isBlank(merchantReq.getCityCode())) {
            throw new RuntimeException("市编号不能为空");
        }
        if (StringUtils.isBlank(merchantReq.getCity())) {
            throw new RuntimeException("市名不能为空");
        }
        if (StringUtils.isBlank(merchantReq.getDistrictCode())) {
            throw new RuntimeException("区编号不能为空");
        }
        if (StringUtils.isBlank(merchantReq.getDistrict())) {
            throw new RuntimeException("区名不能为空");
        }
        if (StringUtils.isBlank(merchantReq.getAddress())) {
            throw new RuntimeException("详细地址不能为空");
        }
        if (merchantReq.getAddress().length() > ADDRESS_CHECK) {
            throw new RuntimeException("详细地址长度不能超过80个字符");
        }
        if (StringUtils.isBlank(merchantReq.getContacts())) {
            throw new RuntimeException("联系人不能为空");
        }
        if (merchantReq.getContacts().length() > NAME_CHECK) {
            throw new RuntimeException("联系人姓名不能超过15个字符");
        }
        if (StringUtils.isBlank(merchantReq.getPhone())) {
            throw new RuntimeException("手机号不能为空");
        }
        if (merchantReq.getPhone().length() > PHONE_CHECK) {
            throw new RuntimeException("手机号长度不能超过11位");
        }
        if (ObjectUtils.isEmpty(merchantReq.getStatus())) {
            throw new RuntimeException("状态不能为空");
        }
        if (StringUtils.isBlank(merchantReq.getProcessedBy())) {
            throw new RuntimeException("处理人不能为空");
        }
    }
}
